namespace Leey.Net.eTerm
{
    using System;
    using System.ComponentModel;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Runtime.CompilerServices;
    using System.Threading;

    public class MyTcpIpServer : Component
    {
        private ManualResetEvent allDone;
        private bool bRun;
        private int bufferSize;
        private Socket listener;
        private ManualResetEvent sendDone;
        private string tcpIpServerIP;
        private int tcpIpServerPort;
        private Thread thread;

        public event ErrorServerEvent ErrorServer;

        public event InceptServerEvent InceptServer;

        public MyTcpIpServer()
        {
            this.bufferSize = 0x800;
            this.tcpIpServerIP = "";
            this.tcpIpServerPort = 0x2af8;
            this.listener = null;
            this.allDone = new ManualResetEvent(false);
            this.sendDone = new ManualResetEvent(false);
            this.thread = null;
            this.bRun = true;
            this.InitializeComponent();
        }

        public MyTcpIpServer(IContainer container)
        {
            this.bufferSize = 0x800;
            this.tcpIpServerIP = "";
            this.tcpIpServerPort = 0x2af8;
            this.listener = null;
            this.allDone = new ManualResetEvent(false);
            this.sendDone = new ManualResetEvent(false);
            this.thread = null;
            this.bRun = true;
            container.Add(this);
            this.InitializeComponent();
        }

        public void Abort()
        {
            if (this.thread != null)
            {
                this.thread.Abort();
                this.listener.Close();
            }
        }

        private void AcceptCallback(IAsyncResult ar)
        {
            Socket workSocket = null;
            try
            {
                try
                {
                    workSocket = ((Socket) ar.AsyncState).EndAccept(ar);
                    StateObject state = new StateObject(this.bufferSize, workSocket);
                    state.workSocket = workSocket;
                    workSocket.BeginReceive(state.buffer, 0, this.bufferSize, SocketFlags.None, new AsyncCallback(this.ReadCallback), state);
                }
                catch (Exception exception)
                {
                    this.OnErrorServerEvent(new ErrorServerEventArgs(exception, workSocket));
                }
            }
            finally
            {
                this.allDone.Set();
            }
        }

        protected override void Dispose(bool disposing)
        {
            this.Abort();
        }

        private void InitializeComponent()
        {
        }

        public void Listening()
        {
            this.bRun = true;
            this.thread = new Thread(new ThreadStart(this.StartListening));
            this.thread.Name = "MyTcpIpServer.Listening";
            this.thread.Start();
        }

        protected virtual void OnErrorServerEvent(ErrorServerEventArgs e)
        {
            if (this.ErrorServer != null)
            {
                this.ErrorServer(this, e);
            }
        }

        protected virtual void OnInceptServerEvent(InceptServerEventArgs e)
        {
            if (this.InceptServer != null)
            {
                this.InceptServer(this, e);
            }
        }

        private void ReadCallback(IAsyncResult ar)
        {
            Socket serverSocket = null;
            try
            {
                lock (ar)
                {
                    StateObject asyncState = (StateObject) ar.AsyncState;
                    serverSocket = asyncState.workSocket;
                    int num = serverSocket.EndReceive(ar);
                    if (num > 0)
                    {
                        for (int i = num; i < asyncState.buffer.Length; i++)
                        {
                            asyncState.buffer[i] = 0;
                        }
                        asyncState.Datastream.Position = 0L;
                        asyncState.Datastream.Write(asyncState.buffer, 0, this.bufferSize);
                        this.OnInceptServerEvent(new InceptServerEventArgs(asyncState.Datastream, asyncState.workSocket, this));
                        if (serverSocket.Connected)
                        {
                            serverSocket.BeginReceive(asyncState.buffer, 0, this.bufferSize, SocketFlags.None, new AsyncCallback(this.ReadCallback), asyncState);
                        }
                    }
                    else
                    {
                        serverSocket.Shutdown(SocketShutdown.Both);
                        serverSocket.Close();
                    }
                }
            }
            catch (Exception exception)
            {
                this.OnErrorServerEvent(new ErrorServerEventArgs(exception, serverSocket));
            }
        }

        private void ReadCallbackOld(IAsyncResult ar)
        {
            Socket serverSocket = null;
            try
            {
                lock (ar)
                {
                    StateObject asyncState = (StateObject) ar.AsyncState;
                    serverSocket = asyncState.workSocket;
                    int num = serverSocket.EndReceive(ar);
                    if (num > 0)
                    {
                        int index = 0;
                        while (index < num)
                        {
                            long num3;
                            int num4;
                            if ((asyncState.Cortrol == 0) && (index < num))
                            {
                                num3 = asyncState.buffer[index];
                                num3 = (num3 << 0x18) & ((long) 0xff000000L);
                                asyncState.packSize = num3;
                                index++;
                                asyncState.Cortrol = 1;
                            }
                            if ((asyncState.Cortrol == 1) && (index < num))
                            {
                                num3 = asyncState.buffer[index];
                                num3 = (num3 << 0x10) & 0xff0000L;
                                asyncState.packSize += num3;
                                index++;
                                asyncState.Cortrol = 2;
                            }
                            if ((asyncState.Cortrol == 2) && (index < num))
                            {
                                num3 = asyncState.buffer[index];
                                num3 = (num3 << 8) & 0xff00L;
                                asyncState.packSize += num3;
                                index++;
                                asyncState.Cortrol = 3;
                            }
                            if ((asyncState.Cortrol == 3) && (index < num))
                            {
                                num3 = asyncState.buffer[index];
                                num3 &= 0xffL;
                                asyncState.packSize = (asyncState.packSize + num3) - 4L;
                                index++;
                                asyncState.Cortrol = 4;
                            }
                            if ((asyncState.Cortrol == 4) && (index < num))
                            {
                                num3 = asyncState.buffer[index];
                                num3 = (num3 << 0x18) & ((long) 0xff000000L);
                                asyncState.residualSize = num3;
                                index++;
                                asyncState.Cortrol = 5;
                                asyncState.packSize -= 1L;
                            }
                            if ((asyncState.Cortrol == 5) && (index < num))
                            {
                                num3 = asyncState.buffer[index];
                                num3 = (num3 << 0x10) & 0xff0000L;
                                asyncState.residualSize += num3;
                                index++;
                                asyncState.Cortrol = 6;
                                asyncState.packSize -= 1L;
                            }
                            if ((asyncState.Cortrol == 6) && (index < num))
                            {
                                num3 = asyncState.buffer[index];
                                num3 = (num3 << 8) & 0xff00L;
                                asyncState.residualSize += num3;
                                index++;
                                asyncState.Cortrol = 7;
                                asyncState.packSize -= 1L;
                            }
                            if ((asyncState.Cortrol == 7) && (index < num))
                            {
                                num3 = asyncState.buffer[index];
                                num3 &= 0xffL;
                                asyncState.residualSize += num3;
                                asyncState.Datastream.SetLength(0L);
                                asyncState.Datastream.Position = 0L;
                                index++;
                                asyncState.Cortrol = 8;
                                asyncState.packSize -= 1L;
                            }
                            if ((asyncState.Cortrol == 8) && (index < num))
                            {
                                num4 = num - index;
                                int count = (int) (asyncState.residualSize - asyncState.Datastream.Length);
                                if (num4 >= count)
                                {
                                    asyncState.Datastream.Write(asyncState.buffer, index, count);
                                    index += count;
                                    this.OnInceptServerEvent(new InceptServerEventArgs(asyncState.Datastream, asyncState.workSocket, this));
                                    asyncState.Cortrol = 9;
                                    asyncState.packSize -= count;
                                }
                                else
                                {
                                    asyncState.Datastream.Write(asyncState.buffer, index, num4);
                                    index += num4;
                                    asyncState.packSize -= num4;
                                }
                            }
                            if ((asyncState.Cortrol == 9) && (index < num))
                            {
                                num4 = num - index;
                                if (num4 < asyncState.packSize)
                                {
                                    asyncState.packSize -= num4;
                                    index += num4;
                                }
                                else
                                {
                                    asyncState.Cortrol = 0;
                                    index += (int) asyncState.packSize;
                                }
                            }
                        }
                        if (serverSocket.Connected)
                        {
                            serverSocket.BeginReceive(asyncState.buffer, 0, this.bufferSize, SocketFlags.None, new AsyncCallback(this.ReadCallback), asyncState);
                        }
                    }
                    else
                    {
                        serverSocket.Shutdown(SocketShutdown.Both);
                        serverSocket.Close();
                    }
                }
            }
            catch (Exception exception)
            {
                this.OnErrorServerEvent(new ErrorServerEventArgs(exception, serverSocket));
            }
        }

        public void Send(Socket ClientSocket, Stream Astream)
        {
            try
            {
                if (!ClientSocket.Connected)
                {
                    throw new Exception("没有连接客户端不可以发送信息!");
                }
                Astream.Position = 0L;
                byte[] buffer = new byte[this.bufferSize];
                int num = (int) ((Astream.Length + 8L) / ((long) this.bufferSize));
                int length = (int) Astream.Length;
                if (((Astream.Length + 8L) % ((long) this.bufferSize)) > 0L)
                {
                    num++;
                }
                num *= this.bufferSize;
                for (int i = Astream.Read(buffer, 0, buffer.Length); i > 0; i = Astream.Read(buffer, 0, buffer.Length))
                {
                    ClientSocket.BeginSend(buffer, 0, (int) Astream.Length, SocketFlags.None, new AsyncCallback(this.SendCallback), ClientSocket);
                    this.sendDone.WaitOne();
                    buffer = new byte[this.bufferSize];
                }
            }
            catch (Exception exception)
            {
                this.OnErrorServerEvent(new ErrorServerEventArgs(exception, ClientSocket));
            }
        }

        private void SendCallback(IAsyncResult ar)
        {
            Socket asyncState = (Socket) ar.AsyncState;
            try
            {
                try
                {
                    int num = asyncState.EndSend(ar);
                }
                catch (Exception exception)
                {
                    this.OnErrorServerEvent(new ErrorServerEventArgs(exception, asyncState));
                }
            }
            finally
            {
                this.sendDone.Set();
            }
        }

        public void SendWithoutHead(Socket ClientSocket, Stream Astream)
        {
            try
            {
                if (!ClientSocket.Connected)
                {
                    throw new Exception("没有连接客户端不可以发送信息!");
                }
                Astream.Position = 0L;
                byte[] buffer = new byte[this.bufferSize];
                int num = (int) ((Astream.Length + 8L) / ((long) this.bufferSize));
                int length = (int) Astream.Length;
                if (((Astream.Length + 8L) % ((long) this.bufferSize)) > 0L)
                {
                    num++;
                }
                num *= this.bufferSize;
                for (int i = Astream.Read(buffer, 0, buffer.Length); i > 0; i = Astream.Read(buffer, 0, buffer.Length))
                {
                    ClientSocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(this.SendCallback), ClientSocket);
                    this.sendDone.WaitOne();
                    buffer = new byte[this.bufferSize];
                }
            }
            catch (Exception exception)
            {
                this.OnErrorServerEvent(new ErrorServerEventArgs(exception, ClientSocket));
            }
        }

        private void StartListening()
        {
            try
            {
                IPAddress any;
                this.listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                if (this.tcpIpServerIP.Trim() == "")
                {
                    any = IPAddress.Any;
                }
                else
                {
                    any = IPAddress.Parse(this.tcpIpServerIP);
                }
                IPEndPoint localEP = new IPEndPoint(any, this.tcpIpServerPort);
                this.listener.Bind(localEP);
                this.listener.Listen(100);
                while (this.bRun)
                {
                    this.allDone.Reset();
                    this.listener.BeginAccept(new AsyncCallback(this.AcceptCallback), this.listener);
                    this.allDone.WaitOne();
                }
            }
            catch (Exception exception)
            {
                this.OnErrorServerEvent(new ErrorServerEventArgs(exception, this.listener));
            }
        }

        public void Stop()
        {
            if (this.thread != null)
            {
                this.bRun = false;
                this.thread.Abort();
                this.listener.Close();
                this.thread = null;
            }
        }

        public bool Activ
        {
            get
            {
                return this.listener.Connected;
            }
        }

        public int BufferSize
        {
            get
            {
                return this.bufferSize;
            }
            set
            {
                this.bufferSize = value;
            }
        }

        public string TcpIpServerIP
        {
            get
            {
                return this.tcpIpServerIP;
            }
            set
            {
                this.tcpIpServerIP = value;
            }
        }

        public int TcpIpServerPort
        {
            get
            {
                return this.tcpIpServerPort;
            }
            set
            {
                this.tcpIpServerPort = value;
            }
        }
    }
}
